<script setup lang="ts">
import {ref, onMounted, reactive} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import request from '@/utils/request'

interface TableInfo {
  tableName: string
  tableComment: string
  createTime: string
  updateTime: string
  engine: string
}

const tableData = ref<TableInfo[]>([])
const loading = ref(false)
const total = ref(0)
const currentPage = ref(1)
const pageSize = ref(10)
const searchTableName = ref('')
const showCreateDialog = ref(false)
const createStep = ref(0)
const createForm = reactive({
  tableName: '',
  tableComment: '',
  engine: 'InnoDB',
  charset: 'utf8mb4',
  fields: [
    { name: '', type: 'varchar', length: 255, primaryKey: false, autoIncrement: false, notNull: false, defaultValue: '', comment: '' }
  ],
  indexes: []
})

const fieldTypes = [
  { value: 'int', name: 'int', needLength: true, defaultLength: 11 },
  { value: 'bigint', name: 'bigint', needLength: true, defaultLength: 20 },
  { value: 'varchar', name: 'varchar', needLength: true, defaultLength: 255 },
  { value: 'char', name: 'char', needLength: true, defaultLength: 1 },
  { value: 'text', name: 'text', needLength: false },
  { value: 'datetime', name: 'datetime', needLength: false },
  { value: 'date', name: 'date', needLength: false },
  { value: 'decimal', name: 'decimal', needLength: true, defaultLength: '10,2' },
  { value: 'float', name: 'float', needLength: true, defaultLength: '10,2' },
  { value: 'double', name: 'double', needLength: true, defaultLength: '10,2' },
  { value: 'tinyint', name: 'tinyint', needLength: true, defaultLength: 4 },
  { value: 'timestamp', name: 'timestamp', needLength: false }
]

const engines = ['InnoDB', 'MyISAM', 'MEMORY']
const charsets = ['utf8mb4', 'utf8', 'latin1']

const fetchData = async () => {
  loading.value = true
  try {
    const response = await request.get('/api/table/list', {
      params: {
        page: currentPage.value,
        pageSize: pageSize.value,
        tableName: searchTableName.value
      }
    })
    tableData.value = response.data.records
    total.value = response.data.total
  } catch (error) {
    ElMessage.error('获取数据失败')
  } finally {
    loading.value = false
  }
}

const handleCurrentChange = (val: number) => {
  currentPage.value = val
  fetchData()
}

const handleSizeChange = (val: number) => {
  pageSize.value = val
  fetchData()
}

const handleSearch = () => {
  currentPage.value = 1
  fetchData()
}

const resetCreateForm = () => {
  createForm.tableName = ''
  createForm.tableComment = ''
  createForm.engine = 'InnoDB'
  createForm.charset = 'utf8mb4'
  createForm.fields = [
    { name: '', type: 'varchar', length: 255, primaryKey: false, autoIncrement: false, notNull: false, defaultValue: '', comment: '' }
  ]
  createForm.indexes = []
  createStep.value = 0
}

const handleFieldTypeChange = (field: any) => {
  const typeConfig = fieldTypes.find(t => t.value === field.type)
  if (typeConfig?.needLength) {
    field.length = typeConfig.defaultLength
  } else {
    field.length = undefined
  }
}

const handleAddField = () => {
  createForm.fields.push({
    name: '',
    type: 'varchar',
    length: 255,
    primaryKey: false,
    autoIncrement: false,
    notNull: false,
    defaultValue: '',
    comment: ''
  })
}

const handleRemoveField = (idx: number) => {
  if (createForm.fields.length > 1) createForm.fields.splice(idx, 1)
}

const handleAddIndex = () => {
  createForm.indexes.push({ name: '', type: 'NORMAL', fields: [], unique: false })
}
const handleRemoveIndex = (idx: number) => {
  createForm.indexes.splice(idx, 1)
}

const handleCreateTable = async () => {
  try {
    await request.post('/api/table/create', createForm)
    ElMessage.success('创建成功')
    showCreateDialog.value = false
    await fetchData()
  } catch (e) {
    ElMessage.error('创建失败')
  }
}

const showCodeGenDialog = ref(false)
const codeGenTable = ref<TableInfo | null>(null)

const codeGenForm = reactive({
  tableName: '',
  tableComment: '',
  types: ['entity', 'controller', 'service', 'serviceImpl', 'mapper', 'xml', 'vue-list', 'vue-form'],
  backendPath: '/d/java_project_all/excelTest/webAdminProject/src/main/java/com/jshan/modules',
  frontendPath: '/d/java_project_all/excelTest/webAdminProject/ops_web/src/views',
  fields: [],
  indexes: []
})

const typeOptions = [
  { label: 'Entity', value: 'entity' },
  { label: 'Controller', value: 'controller' },
  { label: 'Service', value: 'service' },
  { label: 'ServiceImpl', value: 'serviceImpl' },
  { label: 'Mapper', value: 'mapper' },
  { label: 'XML', value: 'xml' },
  { label: '前端列表页', value: 'vue-list' },
  { label: '前端表单页', value: 'vue-form' },
]

const previewDialog = ref(false)
const previewTabs = ref<string[]>([])
const previewCode = ref<Record<string, string>>({})
const previewLoading = ref(false)

const handleGenerate = (row: TableInfo) => {
  codeGenTable.value = row
  codeGenForm.tableName = row.tableName
  codeGenForm.tableComment = row.tableComment
  codeGenForm.fields = [
    { name: 'id', type: 'bigint', comment: '主键' }
  ]
  codeGenForm.indexes = []
  showCodeGenDialog.value = true
}

const handleCodeGenPreview = async () => {
  previewLoading.value = true
  try {
    const req = {
      tableName: codeGenForm.tableName,
      tableComment: codeGenForm.tableComment,
      fields: codeGenForm.fields,
      indexes: codeGenForm.indexes,
      types: codeGenForm.types,
      backendPath: codeGenForm.backendPath,
      frontendPath: codeGenForm.frontendPath
    }
    const res = await request.post('/api/codegen/preview', req)
    previewCode.value = res.data
    previewTabs.value = Object.keys(res.data)
    previewDialog.value = true
  } finally {
    previewLoading.value = false
  }
}

const handleCodeGenGenerate = async () => {
  try {
    await ElMessageBox.confirm('确定要生成代码到指定目录吗？', '提示', { type: 'warning' })
    const req = {
      tableName: codeGenForm.tableName,
      tableComment: codeGenForm.tableComment,
      fields: codeGenForm.fields,
      indexes: codeGenForm.indexes,
      types: codeGenForm.types,
      backendPath: codeGenForm.backendPath,
      frontendPath: codeGenForm.frontendPath
    }
    await request.post('/api/codegen/generate', req)
    ElMessage.success('生成成功！')
    showCodeGenDialog.value = false
  } catch (e) {
    if (e !== 'cancel') ElMessage.error('生成失败')
  }
}

onMounted(async () => {
  await fetchData()
})
</script>

<template>
  <div class="app-container">
    <div class="filter-container">
      <el-button type="primary" @click="() => { showCreateDialog = true; resetCreateForm(); }" style="margin-right: 10px;">
        新增数据表
      </el-button>
      <el-input
          v-model="searchTableName"
          placeholder="请输入表名"
          style="width: 200px;"
          class="filter-item"
          @keyup.enter="handleSearch"
      />
      <el-button type="primary" class="filter-item" @click="handleSearch">
        搜索
      </el-button>
    </div>

    <el-table
        v-loading="loading"
        :data="tableData"
        border
        style="width: 100%"
    >
      <el-table-column type="index" label="序号" width="60" align="center"/>
      <el-table-column
          prop="tableName"
          label="表名"
          align="center"
      />
      <el-table-column
          prop="tableComment"
          label="表注释"
          align="center"
      />
      <el-table-column
          prop="engine"
          label="引擎"
          align="center"
      />
      <el-table-column
          prop="createTime"
          label="创建时间"
          align="center"
      />
      <el-table-column
          prop="updateTime"
          label="更新时间"
          align="center"
      />
      <el-table-column
          label="操作"
          fixed="right"
          align="center"
      >
        <template #default="scope">
          <el-button
              type="primary"
              link
              @click="handleGenerate(scope.row)"
          >
            生成代码
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <div class="pagination-container">
      <el-pagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :total="total"
          :page-sizes="[10, 20, 30, 50]"
          layout="total, sizes, prev, pager, next"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
      />
    </div>

    <el-dialog
      v-model="showCreateDialog"
      title="新建数据表"
      :close-on-click-modal="false"
      draggable
      :destroy-on-close="true"
      class="create-table-dialog"
    >
      <el-steps :active="createStep" finish-status="success" align-center style="margin-bottom: 20px;">
        <el-step title="基本信息" />
        <el-step title="字段设计" />
        <el-step title="索引设计" />
        <el-step title="确认" />
      </el-steps>
      <div v-show="createStep === 0">
        <el-form label-width="100px">
          <el-form-item label="表名">
            <el-input v-model="createForm.tableName" placeholder="如：user" />
          </el-form-item>
          <el-form-item label="表注释">
            <el-input v-model="createForm.tableComment" />
          </el-form-item>
          <el-form-item label="存储引擎">
            <el-select v-model="createForm.engine">
              <el-option v-for="item in engines" :key="item" :label="item" :value="item" />
            </el-select>
          </el-form-item>
          <el-form-item label="字符集">
            <el-select v-model="createForm.charset">
              <el-option v-for="item in charsets" :key="item" :label="item" :value="item" />
            </el-select>
          </el-form-item>
        </el-form>
      </div>
      <div v-show="createStep === 1">
        <el-table :data="createForm.fields" border style="margin-bottom: 10px;">
          <el-table-column prop="name" label="字段名" align="center">
            <template #default="scope">
              <el-input v-model="scope.row.name" />
            </template>
          </el-table-column>
          <el-table-column prop="type" label="类型" align="center">
            <template #default="scope">
              <el-select v-model="scope.row.type" style="width: 100%" @change="() => handleFieldTypeChange(scope.row)">
                <el-option
                  v-for="item in fieldTypes"
                  :key="item.value"
                  :label="item.name"
                  :value="item.value"
                />
              </el-select>
            </template>
          </el-table-column>
          <el-table-column prop="length" label="长度" align="center">
            <template #default="scope">
              <el-input
                v-if="fieldTypes.find(t => t.value === scope.row.type)?.needLength"
                v-model="scope.row.length"
                placeholder="长度"
              />
              <span v-else>-</span>
            </template>
          </el-table-column>
          <el-table-column prop="primaryKey" label="主键" width="60" align="center">
            <template #default="scope">
              <el-checkbox v-model="scope.row.primaryKey" />
            </template>
          </el-table-column>
          <el-table-column prop="autoIncrement" label="自增" width="60" align="center">
            <template #default="scope">
              <el-checkbox v-model="scope.row.autoIncrement" />
            </template>
          </el-table-column>
          <el-table-column prop="notNull" label="非空" width="60" align="center">
            <template #default="scope">
              <el-checkbox v-model="scope.row.notNull" />
            </template>
          </el-table-column>
          <el-table-column prop="defaultValue" label="默认值" align="center">
            <template #default="scope">
              <el-input v-model="scope.row.defaultValue" />
            </template>
          </el-table-column>
          <el-table-column prop="comment" label="注释" align="center">
            <template #default="scope">
              <el-input v-model="scope.row.comment" />
            </template>
          </el-table-column>
          <el-table-column label="操作" align="center">
            <template #default="scope">
              <el-button type="danger" size="small" @click="handleRemoveField(scope.$index)" :disabled="createForm.fields.length === 1">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-button type="primary" @click="handleAddField">添加字段</el-button>
      </div>
      <div v-show="createStep === 2">
        <el-table :data="createForm.indexes" border style="margin-bottom: 10px;">
          <el-table-column prop="name" label="索引名" align="center">
            <template #default="scope">
              <el-input v-model="scope.row.name" />
            </template>
          </el-table-column>
          <el-table-column prop="type" label="类型" align="center">
            <template #default="scope">
              <el-select v-model="scope.row.type" style="width: 100%">
                <el-option label="普通" value="NORMAL" />
                <el-option label="唯一" value="UNIQUE" />
                <el-option label="全文" value="FULLTEXT" />
              </el-select>
            </template>
          </el-table-column>
          <el-table-column prop="fields" label="字段" align="center">
            <template #default="scope">
              <el-select v-model="scope.row.fields" multiple style="width: 100%">
                <el-option v-for="f in createForm.fields" :key="f.name" :label="f.name" :value="f.name" />
              </el-select>
            </template>
          </el-table-column>
          <el-table-column prop="unique" label="唯一" width="60" align="center">
            <template #default="scope">
              <el-checkbox v-model="scope.row.unique" />
            </template>
          </el-table-column>
          <el-table-column label="操作"  align="center">
            <template #default="scope">
              <el-button type="danger" size="small" @click="handleRemoveIndex(scope.$index)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-button type="primary" @click="handleAddIndex">添加索引</el-button>
      </div>
      <div v-show="createStep === 3">
        <el-descriptions title="确认信息" :column="1" border>
          <el-descriptions-item label="表名">{{ createForm.tableName }}</el-descriptions-item>
          <el-descriptions-item label="表注释">{{ createForm.tableComment }}</el-descriptions-item>
          <el-descriptions-item label="引擎">{{ createForm.engine }}</el-descriptions-item>
          <el-descriptions-item label="字符集">{{ createForm.charset }}</el-descriptions-item>
          <el-descriptions-item label="字段">
            <div v-for="f in createForm.fields" :key="f.name">
              {{ f.name }} {{ f.type }}({{ f.length }})
              <span v-if="f.primaryKey">[主键]</span>
              <span v-if="f.autoIncrement">[自增]</span>
              <span v-if="f.notNull">[非空]</span>
              <span v-if="f.defaultValue">[默认:{{ f.defaultValue }}]</span>
              <span v-if="f.comment">[{{ f.comment }}]</span>
            </div>
          </el-descriptions-item>
          <el-descriptions-item label="索引">
            <div v-for="idx in createForm.indexes" :key="idx.name">
              {{ idx.name }} ({{ idx.type }}) 字段: {{ idx.fields.join(',') }} <span v-if="idx.unique">[唯一]</span>
            </div>
          </el-descriptions-item>
        </el-descriptions>
      </div>
      <template #footer>
        <el-button @click="showCreateDialog = false">取消</el-button>
        <el-button v-if="createStep > 0" @click="createStep--">上一步</el-button>
        <el-button v-if="createStep < 3" type="primary" @click="createStep++">下一步</el-button>
        <el-button v-if="createStep === 3" type="success" @click="handleCreateTable">创建</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="showCodeGenDialog" title="代码生成器" width="800px" :close-on-click-modal="false">
      <el-form :model="codeGenForm" label-width="120px" style="max-width: 700px;">
        <el-form-item label="表名">
          <el-input v-model="codeGenForm.tableName" disabled />
        </el-form-item>
        <el-form-item label="表注释">
          <el-input v-model="codeGenForm.tableComment" />
        </el-form-item>
        <el-form-item label="生成类型">
          <el-checkbox-group v-model="codeGenForm.types">
            <el-checkbox v-for="item in typeOptions" :key="item.value" :label="item.value">{{ item.label }}</el-checkbox>
          </el-checkbox-group>
        </el-form-item>
        <el-form-item label="后端生成路径">
          <el-input v-model="codeGenForm.backendPath" placeholder="如 /xxx/xxx/modules" />
        </el-form-item>
        <el-form-item label="前端生成路径">
          <el-input v-model="codeGenForm.frontendPath" placeholder="如 /xxx/xxx/views" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleCodeGenPreview">预览代码</el-button>
          <el-button type="success" @click="handleCodeGenGenerate">生成代码</el-button>
        </el-form-item>
      </el-form>
      <el-dialog v-model="previewDialog" title="代码预览" width="80vw" :close-on-click-modal="false">
        <el-tabs v-model="previewTabs[0]">
          <el-tab-pane v-for="tab in previewTabs" :key="tab" :label="tab">
            <el-input type="textarea" :rows="30" v-model="previewCode[tab]" readonly style="font-family: monospace;" />
          </el-tab-pane>
        </el-tabs>
        <template #footer>
          <el-button @click="previewDialog = false">关闭</el-button>
        </template>
      </el-dialog>
    </el-dialog>
  </div>
</template>

<style scoped>
.el-pagination {
  margin-top: 20px;
  justify-content: flex-end;
}
.app-container {
  padding: 20px;
}

.filter-container {
  padding-bottom: 10px;
}

.filter-item {
  margin-right: 10px;
}

.pagination-container {
  margin-top: 20px;
  text-align: right;
}

:deep(.create-table-dialog) {
  min-width: 800px;
  min-height: 400px;
  resize: both;
  overflow: auto;
}

:deep(.create-table-dialog .el-dialog) {
  margin: 0;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

:deep(.create-table-dialog .el-dialog__body) {
  max-height: calc(90vh - 150px);
  overflow-y: auto;
}

:deep(.create-table-dialog .el-table) {
  width: 100% !important;
}
</style>
